#pragma once 

#include "nrtypes.h"
#include <functional>
#include <vector>

template<bool> struct CompileTimeChecker {	CompileTimeChecker(...); };
template<> struct CompileTimeChecker<false> {};
#define STATIC_CHECK(expr, msg) \
	{ \
		struct ERROR_##msg {}; \
		(void)sizeof(CompileTimeChecker<(expr)>(new ERROR_##msg())); \
	}


class NullType {};

//The longest by default
template <int size=2> struct integer_datatype_selector { typedef QWORD integer_datatype; };
template <> struct integer_datatype_selector<1> { typedef BYTE integer_datatype; };
template <> struct integer_datatype_selector<2> { typedef WORD integer_datatype; };
template <> struct integer_datatype_selector<3> { typedef DWORD integer_datatype; };
template <> struct integer_datatype_selector<4> { typedef DWORD integer_datatype; };

//base template, not used itself
template<class TGenerator>
struct generator_traits
{
	typedef TGenerator Generator;
	typedef int ControlSequence;
	typedef int State;
	typedef int Configuration;
	typedef std::less<int> ConfigurationComparer;
	typedef std::less<int> StateComparer;
	static State next(TGenerator* gen) { return 0; }
	static void setConfiguration(
		TGenerator* gen,
		const Configuration &c)
	{ 
	}
};

template<class T>
class SimpleIterator
{
public:
	virtual bool moveNext() = 0;
	virtual T current() const = 0;
};

template<class T>
class CollectionIterator : public SimpleIterator<T>
{
public:
	CollectionIterator(const std::vector<T> &collection)
		: _it(collection.begin()), _last(collection.end())
	{ }

	bool moveNext()
	{
		_it++;
		return _it != _last;
	}

	T current() const
	{
		return *_it;
	}

private:
	typename std::vector<T>::const_iterator _it;
	typename std::vector<T>::const_iterator _last;
};

//operators categories: left and right
struct left_operator_tag {};
struct right_operator_tag {};

//template for choosing multiplication order statically
template<class C, class OperatorCategory>
struct RotatableInvoker
{
	BYTE op(const C *obj, BYTE (C::*func)(BYTE, BYTE) const, BYTE a, BYTE b) const
	{
		return (obj->*func)(a, b);
	}
};

template<class C>
struct RotatableInvoker<C, right_operator_tag>
{
	BYTE op(const C *obj, BYTE (C::*func)(BYTE, BYTE) const, BYTE a, BYTE b) const
	{
		return (obj->*func)(b, a);
	}
};